require 'MeCab'
require 'kconv'
require 'gdbm'
require 'nkf'
require "Function"
require 'sary'

class DictionaryController < ApplicationController
#  verify :params => :text,:render => {:action => :show_acceptation},:only => :show_acceptation
  before_filter :prepare_variables, :only => :show_acceptation
  before_filter :analyze_text, :only => :show_acceptation
  before_filter :check_list,   :only => :show_acceptation
  
  def show_acceptation
    # キーワードの順番を記憶
    keyword_order = Hash.new
    cnt = 0
    @list.each do |item|
      keyword_order[item] = cnt
      cnt+=1
    end
    # 語義の獲得
    @dict_items = 
      DirectionWord.find(:all,
        :conditions => ["direction_words.text IN (#{'?,' * (@list.size - 1)}?)",@list].flatten,
        :include => :acceptations)
    @dict_items.each do |item|
      @keyword[item.text] = Hash.new
      item.acceptations.each do |acceptation|
        @keyword[item.text][acceptation.id] = acceptation.text if acceptation.text != ""
      end
    end
    # キーワード順に並べ替え
    @keyword = @keyword.to_a.sort{|a,b|
      keyword_order[a[0]] <=> keyword_order[b[0]]
    }
  end

  def show_example2
    g = Function.new
    g.crawl("./app/controllers/bunkei.seed")
    s = Sary::Searcher.new("./app/controllers/mai2002a2_utf8.txt")
    s.enable_cache
    # 例文の取得
    @example_items = Example.find(:all,
      :conditions => ["acceptations.id = ?", params[:acceptation_id]],
      :include => :acceptations)
    @example_items.each do |item|
      # 初期化
      session[:example][item.text] = Hash.new
      session[:example][item.text] = {:visible => true, :active => true, :continue => false, :length => 0, :with_furigana => String.new, :id => params[:id]}
      # 形態素解析
      analyzed_text = MeCab::Tagger.new("-Ochasen").parse(item.text.gsub(/<.+?>/,"")).gsub(/EOS$/,"").strip
      # cssを使ったふりがな付きの例文を作成
      analyzed_text.strip.split("\n").each do |line|
        morph = line.split("\t")
        furigana_flag = false
        if NKF.nkf("--katakana",morph[0]).toutf8 != morph[1].toutf8 and /[0-9０-９~〜]+/ !~ morph[0].toutf8 then
          furigana_flag = true
        end
        session[:example][item.text][:with_furigana] += "<ruby><rb>" if furigana_flag
        session[:example][item.text][:with_furigana] += morph[0].toutf8
        session[:example][item.text][:with_furigana] += "</rb><rp>《</rp><rt>"+NKF.nkf("--hiragana",morph[1]).toutf8+"</rt><rp>》</rp></ruby>" if furigana_flag
        session[:example][item.text][:with_furigana] += "　"  # 全角スペース区切りで表示
      end
      # (記号を除く)形態素数の代入
      length = analyzed_text.gsub(/^.*記号-.*$/,"").strip.split("\n").size-1
      session[:example][item.text][:length] = length
      # 文章長によるスコアの代入
      max = 0.0
      min = 0.0
      max = session[:sentence_max][0].to_f if session[:sentence_max] != nil and session[:sentence_max][0] != nil
      min = session[:sentence_min][0].to_f if session[:sentence_min] != nil and session[:sentence_min][0] != nil
      session[:example][item.text][:length_eva] = (1.0-((max+min-2.0*length.to_f)/(max-min+1.0))*((max+min-2.0*length.to_f)/(max-min+1.0)))
      session[:example][item.text][:length_eva] = 0.0 if session[:example][item.text][:length_eva] <= 0.0
      # 級を調べるために、原形だけの配列を新規に構成
      example_morph_orig_arr = Array.new
      analyzed_text.split("\n").each do |morph_line|
        example_morph_orig_arr << morph_line.split("\t")[2].strip if morph_line.split("\t")[2] != nil
      end
      # 一番難しい単語の級を代入
      @jlpt_voc_level = GDBM.open("./public/gdbm_for_i386_32bit/jlpt_voc_level.gdbm", 0777,GDBM::READER)
      example_morph_orig_arr.each do |orig|
        level = 0
        if @jlpt_voc_level[orig] != nil then
          level = @jlpt_voc_level[orig].to_i
        else
          s.search(orig)
          counts = s.count_occurrences.to_i
          if 237 > counts then
            level = 1
          elsif 492 > counts then
            level = 2
          elsif 751 > counts then
            level = 3
#          elsif 1445 > counts then
          else
            level = 4
          end
        end
        if (session[:example][item.text][:word_rank] == nil or session[:example][item.text][:word_rank].to_i >= level) then
          session[:example][item.text][:word_rank] = level
        end
      end
      @jlpt_voc_level.close
      session[:example][item.text][:word_rank_eva] = (session[:example][item.text][:word_rank].to_i + 1).to_f/5.to_f
      # 一番難しい漢字の級を代入
      @jlpt_kanji_level = GDBM.open("./public/gdbm_for_i386_32bit/jlpt_kanji_level.gdbm",0777,GDBM::READER)
      @jlpt_kanji_level.each do |kanji, rank|
        if /#{kanji.toutf8}/ =~ item.text.toutf8 then
          if session[:example][item.text][:kanji_rank] == nil or session[:example][item.text][:kanji_rank].to_i >= rank.to_i then
            session[:example][item.text][:kanji_rank] = rank.to_i
          end
        end
      end
      @jlpt_kanji_level.close
      session[:example][item.text][:kanji_rank_eva] = (session[:example][item.text][:kanji_rank].to_i+1).to_f / 5.to_f
      # 一番難しい文法の級の代入
      session[:example][item.text][:bunpou_rank] = g.run(item.text.gsub(/<.*?>/,""))
      if session[:example][item.text][:bunpou_rank].to_i != 9 then
        session[:example][item.text][:bunpou_rank_eva] = (session[:example][item.text][:bunpou_rank].to_i+1).to_f / 5.to_f
      else
        session[:example][item.text][:bunpou_rank_eva] = 0.0
      end

      # 重み線形和の計算 スコア付け
      session[:example][item.text][:score] = 0.0
      session[:example][item.text][:score] += session[:example][item.text][:length_eva] * session[:wei_sentence][0].to_f if session[:wei_sentence] != nil
      session[:example][item.text][:score] += session[:example][item.text][:word_rank_eva] * session[:wei_word][0].to_f if session[:wei_word] != nil
      session[:example][item.text][:score] += session[:example][item.text][:kanji_rank_eva] * session[:wei_kanji][0].to_f if session[:wei_kanji] != nil
      session[:example][item.text][:score] += session[:example][item.text][:bunpou_rank_eva] * session[:wei_bunpou][0].to_f if session[:wei_bunpou] != nil

      invisible_flag = false
      # 例文のフィルタリング
      if session[:sentence_min][0].to_i > session[:example][item.text][:length] then
        invisible_flag = true
      end if (session[:sentence_min] != nil and session[:sentence_min][0] != "" and session[:sentence_min][0] != nil)
      if session[:sentence_max][0].to_i < session[:example][item.text][:length] then
        invisible_flag = true
      end if (session[:sentence_max] != nil and session[:sentence_max][0] != "" and session[:sentence_max][0] != nil)
      if session[:word_rank][0].to_i > session[:example][item.text][:word_rank].to_i then
        invisible_flag = true
      end if (session[:word_rank] != nil and session[:word_rank][0] != "" and session[:word_rank][0] != nil)
      if session[:kanji_rank][0].to_i > session[:example][item.text][:kanji_rank].to_i then
        invisible_flag = true
      end if (session[:kanji_rank] != nil and session[:kanji_rank][0] != "" and session[:kanji_rank][0] != nil)
      if session[:bunpou_rank][0].to_i > session[:example][item.text][:bunpou_rank].to_i then
        invisible_flag = true
      end if (session[:bunpou_rank] != nil and session[:bunpou_rank][0] != "" and session[:bunpou_rank][0] != nil)

      if invisible_flag and session[:adapted] != nil then
        if session[:adapted][:visible?] == "0" then
          session[:example][item.text][:visible] = false
        else
          session[:example][item.text][:with_furigana] = "<span style=\"color:gray\">"+session[:example][item.text][:with_furigana]+"</span>"
        end
      end
    end

    # 例文を単語数順に並べ替え
    session[:cur_example] = session[:example].to_a.sort{|a, b|
      a[1][:score]<=>b[1][:score]
    }.reverse
    # 上位5件だけを表示するように設定　:activeをtrueにして他をfalseにする
    cnt = 0
    session[:cur_example].each do |example_set|
      if params[:option] != "continue" and example_set[1][:id] == params[:id] and example_set[1][:visible] == true then
        cnt += 1
        example_set[1][:active] = false if cnt > 5
      end
    end
  end


  private
  def analyze_text
    MeCab::Tagger.new("-Ochasen").parse(session[:input_text]).split("\n").each do |line|
      if /EOS/ !~ line then
        cur_pos = line.split("\t")[3].split("-")[0]
        # 検索の対象とするPOSの指定
        pos_list = ["名詞","副詞","形容詞","動詞"]
        if pos_list.include?(cur_pos) == true then
          base_word = line.split("\t")[2]
          unless @list.include?(base_word) == true
            @list << base_word
          end
        end
      end
    end
  end

  def check_list
    render :action => :show_acceptation if @list.empty?
    return true
  end

  def prepare_variables
    if (session[:input_text] == nil or session[:input_text] != params[:text]) and params[:text] != nil then
      session[:input_text] = params[:text]
    end
    session[:sentence_max] = params[:sentence_max]
    session[:sentence_min] = params[:sentence_min]
    session[:wei_sentence] = params[:wei_sentence]
    session[:kanji_rank] = params[:kanji_rank]
    session[:wei_kanji] = params[:wei_krank]
    session[:word_rank] = params[:word_rank]
    session[:wei_word] = params[:wei_wrank]
    session[:bunpou_rank] = params[:bunpou_rank]
    session[:wei_bunpou] = params[:wei_brank]
    session[:example] = Hash.new
    session[:cur_example] = Array.new
    session[:adapted] = params[:adapted]
    @keyword = Hash.new
    @list = Array.new
  end
end
